package org.erepublik.company.controllers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import org.erepublik.company.ECountry;
import org.erepublik.company.EProductType;
import org.erepublik.company.comparators.ProductComparatorByPriceInGold;
import org.erepublik.company.log.SitesLogger;
import org.erepublik.company.product.Raw;
import org.erepublik.company.searchCriteria.RawsSearchCriteria;
import org.erepublik.company.service.IProductsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/raws.html")
public class RawController extends AbstractController {

    @Autowired // autumatycznie wstrzykiwany obiekt
    private SitesLogger sitesLogger; 
    
    @Autowired // autumatycznie wstrzykiwany obiekt
    private IProductsService productService; 
    
    @RequestMapping(method = RequestMethod.GET)
    public String showForm(ModelMap model) {
        fillModelMap(model);
        Raw[] products = productService.getRaws(null, EProductType.IRON);
        products = groupRaws(products);
        products = shrinkTable(products);
        model.addAttribute("updateTime", productService.getMinutesSinceRawUpdate() );
        model.addAttribute("products", products);
        model.addAttribute("rawsSearchCriteria", new RawsSearchCriteria());
        sitesLogger.log("RAWS", "Country: null Raw: Iron Group: true");
        return "raws";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String showList(ModelMap model, @ModelAttribute("rawsSearchCriteria") RawsSearchCriteria criteria) {
        fillModelMap(model);
        EProductType productType = null;
        if (criteria.getRaws()!=null)
            productType = EProductType.valueOf( criteria.getRaws().toString() );
        Raw[] products = productService.getRaws(criteria.getCountry(), productType );
        if (criteria.isGroup())
            products = groupRaws(products);
        products = shrinkTable(products);
        model.addAttribute("updateTime", productService.getMinutesSinceRawUpdate() );
        model.addAttribute("products", products);
        sitesLogger.log("RAWS", "Country: "+criteria.getCountry()+
                " Raw: "+criteria.getRaws()+
                " Group: "+criteria.isGroup());
        return "raws";
    }
    
    final int MAX_SIZE=100; // maksymalna ilosc wyswietlanych produktow
    // skraca tabele do MAX_SIZE produktow
    private Raw[] shrinkTable(Raw[] products) {
        if (products.length <= MAX_SIZE)
            return products;
        else {
            Raw[] newTable = new Raw[MAX_SIZE];
            for (int i=0; i < MAX_SIZE; i++) {
                newTable[i]=products[i];
            }
            return newTable;
        }
    }
    
    
    private Raw[] groupRaws(Raw[] raws) {
        
      EProductType[] types = new EProductType[] { EProductType.IRON, EProductType.GRAIN, EProductType.OIL, EProductType.STONE, EProductType.TITANIUM };
      ArrayList<Raw> rawsList = new ArrayList<Raw>();
      for (EProductType type : types) {
            
          HashMap<ECountry, Raw> bestOffersMap = new HashMap<ECountry, Raw>();
          ECountry[] countries = ECountry.values();
          for (ECountry country : countries) {
              Raw raw = new Raw(type);
              raw.setPrice(9999.0d);
              bestOffersMap.put(country, raw );
          }
          
          for (Raw raw : raws) {
              if (raw.getProductType() != type)
                  continue;
              double bestPrice = bestOffersMap.get( raw.getCountry() ).getPrice();
              if (bestPrice==raw.getPrice()) {
                  Raw obj = bestOffersMap.get( raw.getCountry() );
                  obj.setQuantity( obj.getQuantity() + raw.getQuantity() );
                  obj.setOfferNumbers( obj.getOfferNumbers()+1 );
              }
              if (bestPrice>raw.getPrice()) {
                  Raw obj = raw.clone();
                  obj.setOfferNumbers(1);
                  bestOffersMap.put( raw.getCountry(), obj );
              }
          }       
          
          
          for (ECountry country : countries) {
              Raw raw = bestOffersMap.get( country );
           
              if (raw.getPrice()!=9999.0d)
                  rawsList.add(raw);
          }
      }
      
      Raw[] newArray = rawsList.toArray(new Raw[0]);
      Arrays.sort(newArray, new ProductComparatorByPriceInGold());
      
      return newArray;
  }
    
    
}
